package data

import (
	"context"
	"gorm.io/gorm"
	"math"
)

type PageParam struct {
	PageNum  int64 `protobuf:"varint,1,opt,name=pageNum,proto3" json:"pageNum,omitempty"`
	PageSize int64 `protobuf:"varint,2,opt,name=pageSize,proto3" json:"pageSize,omitempty"`
}

type PageQuery[T any] struct {
	PageParam PageParam `json:"pageParam"`
	po        T
}

type PageInfo struct {
	Total    int64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"`
	PageNum  int64 `protobuf:"varint,2,opt,name=pageNum,proto3" json:"pageNum,omitempty"`
	PageSize int64 `protobuf:"varint,3,opt,name=pageSize,proto3" json:"pageSize,omitempty"`
	Pages    int64 `protobuf:"varint,4,opt,name=pages,proto3" json:"pages,omitempty"`
}

// 标准分页结构体，接收查询结果的结构体
type PageResult[T any] struct {
	PageInfo PageInfo `json:"page_info"`
	List     []T      `json:"data"`
}

func GetResult[T any](ctx context.Context, p *PageQuery[T]) (res *PageResult[T], e error) {
	page := &PageResult[T]{}
	page.PageInfo.PageNum = p.PageParam.PageNum
	page.PageInfo.PageSize = p.PageParam.PageSize
	db := BaseMapper[T]{}.DB(ctx)
	err := db.Count(&page.PageInfo.Total).Error
	if err != nil {
		return page, err
	}
	if page.PageInfo.Total == 0 {
		page.List = []T{}
		return page, err
	}
	e = db.Where(p.po).Scopes(Paginate(page)).Find(&page.List).Error
	return page, e
}

func Paginate[T any](page *PageResult[T]) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if page.PageInfo.PageNum <= 0 {
			page.PageInfo.PageNum = 1
		}
		switch {
		case page.PageInfo.PageSize > 10000:
			page.PageInfo.PageSize = 10000 // 限制一下分页大小
		case page.PageInfo.PageSize <= 0:
			page.PageInfo.PageSize = 10
		}
		// 使用浮点数除法，然后向上取整
		page.PageInfo.Pages = int64(math.Ceil(float64(page.PageInfo.Total) / float64(page.PageInfo.PageSize)))
		p := page.PageInfo.PageNum
		if page.PageInfo.PageNum > page.PageInfo.Pages {
			p = page.PageInfo.Pages
		}
		size := page.PageInfo.PageSize
		offset := int((p - 1) * size)
		return db.Offset(offset).Limit(int(size))
	}
}
